home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / dev / c / Includes.lzh / inc / includes.c next >
Encoding:
C/C++ Source or Header  |  1992-04-22  |  6.4 KB  |  387 lines

  1. /*
  2.  * includes.c - dumps recursively all include files needed by C programs
  3.  *
  4.  * Bruno Costa - 24 Jan 90 - 22 Apr 92
  5.  *
  6.  */
  7.  
  8. #define DEBUG 0
  9.  
  10. /* #define UNIX  1 */
  11. #define AMIGA 1
  12.  
  13. #include <ctype.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17.  
  18. #define TRUE 1
  19. #define FALSE 0
  20.  
  21. #define MAXPATH 100
  22. #define MAXLINE 200
  23. #define HASHSIZE 101
  24.  
  25. #define loop for(;;)
  26. #define streq(a,b) (!strcmp(a,b))
  27. #define prefix(pref,str) (!strncmp(pref,str,strlen(pref)))
  28. #define isuser(name) ((*(name) == '"') ? 1 : 0)
  29. #define issyst(name) ((*(name) == '<') ? 1 : 0)
  30.  
  31. typedef struct ITEM {
  32.   struct ITEM *next;
  33.   char *name;
  34.   int done;
  35. } item;
  36.  
  37. item *hashtable[HASHSIZE];
  38.  
  39. int verbose = TRUE;
  40. int makemode = FALSE;
  41. int sysdump = FALSE;
  42.  
  43. #if defined (AMIGA)
  44. char *incdir = "INCLUDE:";
  45. #elif defined (UNIX)
  46. char *incdir = "/usr/include/";
  47. #endif
  48.  
  49.  
  50. void inithash (void)
  51. {
  52.  item **p, **q;
  53.  
  54.  for (p = hashtable, q = hashtable + HASHSIZE; p < q; p++)
  55.    *p = NULL;
  56. }
  57.  
  58.  
  59. unsigned hash (char *str)
  60. {
  61.  unsigned value;
  62.  
  63.  for (value = 0; *str; str++)
  64.    value = *str + 31 * value;
  65.  
  66.  return value % HASHSIZE;
  67. }
  68.  
  69.  
  70. item *lookup (char *name)
  71. {
  72.  item *p;
  73.  
  74.  for (p = hashtable[hash (name)]; p; p = p->next)
  75.    if (streq (name, p->name))
  76.      return p;
  77.  
  78.  return NULL;
  79. }
  80.  
  81.  
  82. item *install (char *name)
  83. {
  84.  item *p;
  85.  unsigned int h;
  86.  
  87.  if ((p = lookup (name)) == NULL)
  88.  {
  89.    p = (item *) malloc (sizeof (item));
  90.    if (p == NULL  ||  (p->name = strdup (name)) == NULL)
  91.    {
  92.      fputs ("includes: out of mem\n", stderr);
  93.      exit (20);
  94.    }
  95.    p->done = FALSE;
  96.    h = hash (name);
  97.    p->next = hashtable[h];
  98.    hashtable[h] = p;
  99.  }
  100.  
  101.  return p;
  102. }
  103.  
  104.  
  105. int nospaces (char *str)
  106. {
  107.  register char *p, *q;
  108.  
  109.  for (p = str, q = str; *p; p++)
  110.    if (!isspace (*p))
  111.      *q++ = tolower (*p);
  112.  
  113.  *q = '\0';
  114.  
  115.  return q - str;
  116. }
  117.  
  118.  
  119. int mkpath (char *path, char *name)
  120. {
  121.  path[0] = '\0';
  122.  switch (name[0])
  123.  {
  124.    case '<':        /* system directory */
  125.      strcat (path, incdir);
  126.  
  127.    case '"':        /* current directory */
  128.      strcat (path, name + 1);
  129.      return TRUE;
  130.      break;
  131.  
  132.    default:        /* current directory, name given in command line */
  133.      strcat (path, name);
  134.      return FALSE;
  135.      break;
  136.  }
  137.  /* NOTREACHED */
  138. }
  139.  
  140.  
  141. #if AMIGA
  142. int specialparse (char *fname)
  143. {
  144.  char c, line[MAXLINE];
  145.  int compactheader = FALSE;
  146.  FILE *f;
  147.  
  148.  f = fopen (fname, "rb");
  149.  
  150.  if (f  &&  (fgetc (f) == 0x80))
  151.  {
  152.    compactheader = TRUE;
  153. #if DEBUG
  154.    printf ("processing compact header %s\n", fname);
  155. #endif
  156.    loop
  157.    {
  158.      c = fgetc (f);
  159.      if (c == EOF)
  160.        break;
  161.      if (c == 0x8C)    /* include directive */
  162.      {
  163.        int i = 0;
  164.        char delim;
  165.  
  166.        line [i++] = (char)fgetc (f);
  167.        delim = (line[0] == '<') ? '>' : line[0];
  168.        while (i < MAXLINE  &&  (line [i++] = (char)fgetc (f)) != delim)
  169.          ;
  170.        line [i-1] = '\0';
  171. #if DEBUG
  172.        printf ("  found include %s%c\n", line, delim);
  173. #endif
  174.        if (sysdump  ||  isuser (line))
  175.          install (line);
  176.      }
  177.    }
  178.  }
  179.  
  180.  if (f)
  181.    fclose (f);
  182.  return (compactheader);
  183. }
  184. #endif
  185.  
  186.  
  187. int parsefile (char *fname)
  188. {
  189.  char line[MAXLINE];
  190.  FILE *f;
  191.  
  192. #if DEBUG
  193.  printf ("parsing %s\n", fname);
  194. #endif
  195.  
  196. #if AMIGA
  197.  if (specialparse (fname))
  198.    return TRUE;
  199. #endif
  200.  
  201.  f = fopen (fname, "r");
  202.  if (f)
  203.  {
  204.    while (fgets (line, MAXLINE, f))
  205.      if (line[0] == '#')
  206.      {
  207.        nospaces (line);
  208.        if (prefix ("include", &line[1]))
  209.        {
  210.          char *end;
  211.          if (isuser (&line[8]))
  212.            end = strchr (&line[9], '"');
  213.          else
  214.            end = strchr (&line[9], '>');
  215.          if (!end)
  216.          {
  217.            fputs ("includes: improper include directive in '", stderr);
  218.            fputs (fname, stderr);
  219.            fputs ("'\n", stderr);
  220.            continue;
  221.          }
  222.          *end = '\0';
  223.          if (sysdump  ||  isuser (&line[8]))
  224.            install (&line[8]);
  225.        }
  226.      }
  227.    fclose (f);
  228.    return TRUE;
  229.  }
  230.  else if (verbose)
  231.  {
  232.    fputs ("includes: could not open '", stderr);
  233.    fputs (fname, stderr);
  234.    fputs ("'\n", stderr);
  235.    return FALSE;
  236.  }
  237. }
  238.  
  239.  
  240. void incparse (char *fname)
  241. {
  242.  char pathname[MAXPATH];
  243.  item *me;
  244.  
  245.  me = install (fname);
  246.  
  247.  if (parsefile (fname))
  248.  {
  249.    item *p;
  250.    int i, more;
  251.  
  252.    me->done = TRUE;
  253.  
  254.    do
  255.    {
  256.      more = FALSE;
  257.      for (i = 0; i < HASHSIZE; i++)
  258.        for (p = hashtable[i]; p; p = p->next)
  259.          if (!p->done)
  260.          {
  261.            more = TRUE;
  262.            mkpath (pathname, p->name);
  263.            if (!parsefile (pathname)  &&  isuser (p->name)  &&  sysdump)  /* TODO:? */
  264.            {
  265.              p->name[0] = '<';
  266.              if (lookup (p->name) == NULL)
  267.              {
  268.                if (sysdump)
  269.                {
  270.                  mkpath (pathname, p->name);
  271.                  if (!parsefile (pathname))
  272.                    p->name[0] = '"';
  273.                }
  274.              }
  275.              else
  276.                p->name[0] = '"';
  277.            }
  278.            p->done = TRUE;
  279.          }
  280.    } while (more);
  281.  }
  282. }
  283.  
  284.  
  285. void incdump (void (*dumpfunc) (char *))
  286. {
  287.  item *p;
  288.  int i, more;
  289.  
  290. #if DEBUG
  291.  printf ("\ndumping ...\n");
  292. #endif
  293.  
  294.  do
  295.    for (more = FALSE, i = 0; i < HASHSIZE; i++)
  296.      for (p = hashtable[i]; p; p = p->next)
  297.      {
  298.        char path[MAXPATH];
  299.        if (mkpath (path, p->name))    /* dump only if include file */
  300.        {
  301.          if (sysdump || isuser (p->name))
  302.            (*dumpfunc) (path);
  303.        }
  304. #if DEBUG
  305.        else
  306.        {
  307.          fputs (path, stdout);
  308.          puts (" (cli)");
  309.        }
  310. #endif
  311.      }
  312.  while (more);
  313.  
  314. }
  315.  
  316.  
  317. void putfile (char *name)
  318. {
  319.  fputc (' ', stdout);
  320.  fputs (name, stdout);
  321. }
  322.  
  323.  
  324. void main (int argc, char *argv[])
  325. {
  326.  int i, j, c;
  327.  
  328.  if (argc == 1)
  329.  {
  330.    fputs ("includes 1.2 - (c) 1992 by Bruno Costa\n"
  331.           "usage: includes [-ms] <C Sources> ...\n"
  332.           "       -m = dump inclusions in makefile format\n"
  333.           "       -s = process system include files too\n"
  334.           "       -q = quiet operation\n", stderr);
  335.    exit (5);
  336.  }
  337.  
  338.  i = 1;
  339.  if (argv[i][0] == '-')
  340.  {
  341.    for (j = 1; c = argv[i][j]; j++)
  342.      switch (c)
  343.      {
  344.        case 'm':
  345.          makemode = TRUE;
  346.          break;
  347.        case 's':
  348.          sysdump = TRUE;
  349.          break;
  350.        case 'q':
  351.          verbose = FALSE;
  352.          break;
  353.        default:
  354.          fputs ("includes: unknown option", stderr);
  355.          exit (10);
  356.          break;
  357.      }
  358.    ++i;
  359.  }
  360.  
  361.  if (makemode)
  362.  {
  363.    for (; i < argc; i++)
  364.    {
  365.      fputs (argv[i], stdout);
  366.      fputc (':', stdout);
  367.  
  368.      inithash ();
  369.      incparse (argv[i]);
  370.      incdump (putfile);
  371.  
  372.      fputc ('\n', stdout);
  373.    }
  374.  }
  375.  else
  376.  {
  377.    inithash ();
  378.  
  379.    for (; i < argc; i++)
  380.      incparse (argv[i]);
  381.  
  382.    incdump (puts);
  383.  }
  384.  
  385.  exit (0);
  386. }
  387.